package com.a918.service.impl;

import com.a918.dao.*;
import com.a918.entity.*;
import com.a918.service.EvaluateService;
import com.a918.util.ParamUtil;
import com.a918.util.shangquanF;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class EvaluateServiceImp implements EvaluateService {
    private OrgmonthMapper orgmonthMapper;
    private OrgdailyMapper orgdailyMapper;
    private OrgcollectionMapper orgcollectionMapper;
    private WeightMapper weightMapper;
    private UserMapper userMapper;


    @Autowired
    public EvaluateServiceImp(OrgmonthMapper orgmonthMapper, OrgdailyMapper orgdailyMapper, OrgcollectionMapper orgcollectionMapper, WeightMapper weightMapper,UserMapper userMapper){
        this.orgmonthMapper = orgmonthMapper;
        this.orgdailyMapper = orgdailyMapper;
        this.orgcollectionMapper=orgcollectionMapper;
        this.weightMapper = weightMapper;
        this.userMapper=userMapper;
    }


    @Override
    public Orgmonth getByNameAndYuefen(String orgCode,String yuefen){
        return orgmonthMapper.getByNameAndYuefen(orgCode,yuefen);
    }

    @Override
    public Orgmonth selectAllData(){
        return orgmonthMapper.selectAllData();
    }

    @Override
    public Orgmonth getMaxShangquanf(String yuefen){
        return orgmonthMapper.getMaxShangquanf(yuefen);
    }

    @Override
    public List<Double> getMaxAttribute() {
        List<String> list = Arrays.asList("average_age","workload","delivery_rate","labor_productivity","daily_max_waybill_count","avg_delivery_count_rate");
        List<Double> maxList = new ArrayList<>();
        for (String zb : list) {
            maxList.add(orgmonthMapper.getMinOrMaxZhibiaoOfAll(zb, 1));
        }
        return maxList;
    }

    @Override
    public Map<String,Object> getMinAndMaxZhibiao(String yuefen) {
        Map<String,Object> result=new HashMap();
        Map<String,Map<String,Double>> twoMaps=new HashMap();
        List<String> list = Arrays.asList("AverageAge","AvgWorkLength","DeliveryCount","WaybillNoCount","DailyMaxWaybillCount","AvgDeliveryCountRate","Workload","LaborProductivity","DeliveryRate");
        List<String> list1 = Arrays.asList("average_age","avg_work_length","delivery_count","waybill_no_count","daily_max_waybill_count","avg_delivery_count_rate","workload","labor_productivity","delivery_rate");
        Map<String,Double> maxMap=new HashMap<>();
        Map<String,Double> minMap=new HashMap<>();
        try {
            for(int i = 0; i < list.size(); i++){
                String zb = list.get(i);
                String zb1 = list1.get(i);
                if(orgmonthMapper.getMinOrMaxZhibiao(zb1,yuefen,0).size()==0){
                    result.put("res","fail");
                    return new JSONObject(result);
                };
                Orgmonth orgmonth=orgmonthMapper.getMinOrMaxZhibiao(zb1,yuefen,0).get(0);
                Method m=orgmonth.getClass().getDeclaredMethod("get"+list.get(i));
                minMap.put(zb,Double.valueOf(m.invoke(orgmonth).toString()));
                orgmonth=orgmonthMapper.getMinOrMaxZhibiao(zb1,yuefen,1).get(0);
                maxMap.put(zb,Double.valueOf(m.invoke(orgmonth).toString()));
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        twoMaps.put("min",minMap);
        twoMaps.put("max",maxMap);
        result.put("res",twoMaps);
        return result;
    }

    @Override
    public double[] addshangquanF(String yuefen) {
        List<Orgmonth> orgmonths = orgmonthMapper.getAllByYufen(yuefen);
        int n, m;
        n = orgmonths.size();
        m = 6;
        double wangdian[][] = new double[n][m];
        for (int i = 0; i < n; i++) {
            Orgmonth orgmonth = orgmonths.get(i);
            wangdian[i][0] = orgmonth.getDailyMaxWaybillCount();//单日最大处理量
            wangdian[i][1] = 1.0 / orgmonth.getAverageAge();//时效
            wangdian[i][2] = orgmonth.getLaborProductivity();//劳动生产率
            wangdian[i][3] = orgmonth.getAvgDeliveryCountRate();//当日派件率
            wangdian[i][4] = orgmonth.getDeliveryRate();//人员利用率
            double workload = orgmonth.getWorkload();//工作负荷
            double max = orgmonthMapper.getMaxWorkload(orgmonth.getYuefen());
            double min = orgmonthMapper.getMinWorkload(orgmonth.getYuefen());
            if (workload < 100) {
                wangdian[i][5] = (orgmonth.getWorkload() - min) / (100- min);
            } else {
                wangdian[i][5] = (max - orgmonth.getWorkload()) / (max - 100);
            }
        }
        Object[] res = shangquanF.shangquan(wangdian);
        double[] shangquan = (double[]) res[0];
        double[][] guiyi = (double[][]) res[1];
        for (int i = 0; i < n; i++) {
            Orgmonth orgmonth = orgmonths.get(i);
            orgmonth.setShangquanf(shangquan[i]);
            orgmonth.setMaxScore(guiyi[i][0] * 100);
            orgmonth.setAgeScore(guiyi[i][1] * 100);
            orgmonth.setLaborScore(guiyi[i][2] * 100);
            orgmonth.setDailyScore(guiyi[i][3] * 100);
            orgmonth.setStaffScore(guiyi[i][4] * 100);
            orgmonth.setLoadScore(wangdian[i][5] * 100);
            orgmonthMapper.updateByPrimaryKey(orgmonth);
        }

        double W[] = new double[m];

        for (int i = n;i < (n+m); i++){
            W[i-n] = shangquan[i];
        }
        return W;
    }

    @Override
    public void addinc_coef(String wangdian, String yuefen) {
        Orgmonth orgmonth = orgmonthMapper.getByNameAndYuefen(wangdian, yuefen);
        double index2 = orgmonth.getShangquanf();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Date date = new Date();
        try {
            date = sdf.parse(orgmonth.getYuefen());
        } catch (Exception e) {
            e.printStackTrace();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) - 1);
        String newdate = sdf.format(calendar.getTime());//上一个月的字符型表示
        Orgmonth orgmonth1 = orgmonthMapper.getByNameAndYuefen(wangdian, newdate);
        double inc_coef;
        if (orgmonth1 == null) {
            inc_coef = 1;
        } else{
            double index1 = orgmonth1.getShangquanf();
            double x =  -(index2-index1)/index1;
            double e = Math.E;//自然常数e的近似值
            double d = Math.pow(e, x);//e^x
            inc_coef = 2/(1+d);
        }
        orgmonth.setIncCoef(inc_coef);
        orgmonth.setDynamicEff(inc_coef * index2);
        orgmonthMapper.updateByPrimaryKey(orgmonth);
    }


    public List<Orgmonth> addRank(List<Orgmonth> list1){
        for(Orgmonth orgmonth: list1){
            try{
                Double d=orgmonth.getShangquanf();
                if (d<=25){orgmonth.setRank("D");}
                else if (d<=50){orgmonth.setRank("C");}
                else if (d<=75){orgmonth.setRank("B");}
                else {orgmonth.setRank("A");}
            }
            catch (Exception e){
                orgmonth.setRank("D");
            }

        }
        return list1;

    }

    @Override
    public List<Orgmonth> getOrgList(Map<String, String> paramMap) {
        String username=paramMap.get("username");
        String orgCode=paramMap.get("orgCode");

        // 点击收藏orgCode时
        if(username!=null && !username.equals("") && orgCode!=null && !orgCode.equals("")){
            Orgcollection orgcollection=new Orgcollection();
            orgcollection.setOrgCode(orgCode);
            orgcollection.setUsername(username);
            try{
                Integer id=orgcollectionMapper.query(orgcollection);
            }
            catch (Exception e1){
                // query结果为null，即还未收藏
                orgcollectionMapper.insert(orgcollection);
            }
        }

        try{
            switch (paramMap.get("field")){
                case "avgDeliveryCountRate":        //当日派件率
                    paramMap.put("field","avg_delivery_count_rate");
                    break;
                case "averageAge":          //派送时效
                    paramMap.put("field","average_age");
                    break;
                case "laborProductivity":           //劳动生产率
                    paramMap.put("field","labor_productivity");
                    break;
                case "deliveryRate":            //人员利用率
                    paramMap.put("field","delivery_rate");
                    break;
                case "dailyMaxWaybillCount":        //最大派送能力
                    paramMap.put("field","daily_max_waybill_count");
                    break;
            }

            return orgmonthMapper.getOrderedOrgList(paramMap);
        }
        catch(Exception e2){
            // 如果不排序，分页返回
            PageHelper.startPage(Integer.parseInt(paramMap.get("page")), Integer.parseInt(paramMap.get("limit")));
            return orgmonthMapper.getOrgList(paramMap);
        }

    }

    @Override
    public List<Orgmonth> getOrgListCollected(Map<String, String> paramMap) {
        String username=paramMap.get("username");
        String orgCode=paramMap.get("orgCode");

        // 取消收藏orgCode
        if(username!=null && !username.equals("") && orgCode!=null && !orgCode.equals("")){
            Orgcollection orgcollection=new Orgcollection();
            orgcollection.setOrgCode(orgCode);
            orgcollection.setUsername(username);
            try{
                Integer id=orgcollectionMapper.query(orgcollection);
                orgcollectionMapper.deleteByPrimaryKey(id);
            }
            catch (Exception e1){
                System.out.println(e1);
            }
        }
        try{
            switch (paramMap.get("field")){
                case "avgWorkLength":
                    paramMap.put("field","avg_work_length");
                    break;
                case "averageAge":
                    paramMap.put("field","average_age");
                    break;
                case "deliveryCount":
                    paramMap.put("field","delivery_count");
                    break;
                case "waybillNoCount":
                    paramMap.put("field","waybill_no_count");
                    break;
                case "dailyMaxWaybillCount":
                    paramMap.put("field","daily_max_waybill_count");
                    break;
            }
            return orgmonthMapper.getOrderedOrgListCollected(paramMap);
        }
        catch(Exception e){
            // 如果不排序，分页返回
            PageHelper.startPage(Integer.parseInt(paramMap.get("page")), Integer.parseInt(paramMap.get("limit")));
            return orgmonthMapper.getOrgListCollected(paramMap);
        }
    }


    @Override
    public Orgdaily getWorkLengthByNameAndDate(String wangdian, String date) {
        return orgdailyMapper.getByNameAndDate(wangdian, date);
    }

    @Override
    public Map<String,Object> getWorkLengthByNameAndDateRange(String wangdian, String dateBgn, String dateEnd) {
        List<Orgdaily> orgdailyList = orgdailyMapper.getByNameAndDateRange(wangdian, dateBgn, dateEnd);
        Map<String,Object> res=new HashMap<>();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        if(!orgdailyList.isEmpty()) {
            List<String> dateList=new ArrayList<>();
            List<Double>  workLengthList=new ArrayList<>();
            DecimalFormat df = new DecimalFormat("#.00");
            for (Orgdaily orgdaily : orgdailyList) {
                dateList.add(sf.format(orgdaily.getBusinessDate()));
                workLengthList.add(orgdaily.getWorkLength() / 10 * 100);
            }
            res.put("date",dateList);
            res.put("worklength",workLengthList);
            res.put("res","success");
        }else{
            res.put("res","fail");
        }
        return res;
    }

    @Override
    public List<String> getAllOrgCode() {
        return orgmonthMapper.getAllOrgCode();
    }

    @Override
    public List<String> getAllOrgCodeByYuefen(String yuefen) {
        return orgmonthMapper.getAllOrgCodeByYuefen(yuefen);
    }

    @Override
    public List<String> getCollectedOrgCode(String username) {
        return orgcollectionMapper.getCollectedOrgCode(username);
    }

    @Override
    public Map<String, Object> getYewuliangByNameAndDateRange(String wangdian, String dateBgn, String dateEnd) {
        List<Orgdaily> orgdailyList = orgdailyMapper.getByNameAndDateRange(wangdian, dateBgn, dateEnd);
        Map<String,Object> res=new HashMap<>();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        if(!orgdailyList.isEmpty()) {
            List<String> dateList=new ArrayList<>();
            List<Integer>  YewuliangList=new ArrayList<>();
            for (Orgdaily orgdaily : orgdailyList) {
                dateList.add(sf.format(orgdaily.getBusinessDate()));
                YewuliangList.add(orgdaily.getWaybillCount());
            }
            res.put("date",dateList);
            res.put("Yewuliang",YewuliangList);
            res.put("res","success");
        }else{
            res.put("res","fail");
        }
        return res;
    }

    @Override
    public Map<String, Object> getShixiaoByNameAndDateRange(String wangdian, String dateBgn, String dateEnd) {
        List<Orgdaily> orgdailyList = orgdailyMapper.getByNameAndDateRange(wangdian, dateBgn, dateEnd);
        Map<String,Object> res=new HashMap<>();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        if(!orgdailyList.isEmpty()) {
            List<String> dateList=new ArrayList<>();
            List<Double>  ShixiaoList=new ArrayList<>();
            for (Orgdaily orgdaily : orgdailyList) {
                dateList.add(sf.format(orgdaily.getBusinessDate()));
                ShixiaoList.add(orgdaily.getAverageAge());
            }
            res.put("date",dateList);
            res.put("Shixiao",ShixiaoList);
            res.put("res","success");

        }else{
            res.put("res","fail");
        }
        return res;
    }

    @Override
    public Map<String, Object> getShengchanlvByNameAndDateRange(String wangdian, String dateBgn, String dateEnd) {
        List<Orgdaily> orgdailyList = orgdailyMapper.getByNameAndDateRange(wangdian, dateBgn, dateEnd);
        Map<String,Object> res=new HashMap<>();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        if(!orgdailyList.isEmpty()) {
            List<String> dateList=new ArrayList<>();
            List<Double>  shengchanlvList=new ArrayList<>();
            for (Orgdaily orgdaily : orgdailyList) {
                dateList.add(sf.format(orgdaily.getBusinessDate()));
                Double shengchanlv= (double)orgdaily.getDeliveryCountOfDay()/(double)orgdaily.getDeliveryCount();
                shengchanlvList.add(shengchanlv);
            }
            res.put("date",dateList);
            res.put("shengchanlv",shengchanlvList);
            res.put("res","success");

        }else{
            res.put("res","fail");
        }
        return res;
    }

    @Override
    public Map<String, Object> getDeliveryCountByNameAndDateRange(String wangdian, String dateBgn, String dateEnd) {
        // 人员利用率变化
        List<Orgdaily> orgdailyList = orgdailyMapper.getByNameAndDateRange(wangdian, dateBgn, dateEnd);
        Map<String,Object> res=new HashMap<>();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        if(!orgdailyList.isEmpty()) {
            Orgmonth orgmonth = orgmonthMapper.getByNameAndYuefen(wangdian, dateBgn.substring(0,7));
            int countOfMonth;
            if (orgmonth == null) {
                // 没有orgMonth记录时，取list里的最大值
                Orgdaily max = orgdailyList.stream().max(Comparator.comparing(Orgdaily::getDeliveryCount)).orElse(orgdailyList.get(orgdailyList.size()-1));
                countOfMonth = max.getDeliveryCount();
            } else {
                countOfMonth = orgmonth.getDeliveryCount();
            }
            List<String> dateList=new ArrayList<>();
            List<Double>  deliveryCountList=new ArrayList<>();
            for (Orgdaily orgdaily : orgdailyList) {
                dateList.add(sf.format(orgdaily.getBusinessDate()));

                deliveryCountList.add(Math.min(100.0, 100.0 * orgdaily.getDeliveryCount() / countOfMonth));
            }
            res.put("date",dateList);
            res.put("deliveryCount",deliveryCountList);
            res.put("res","success");

        }else{
            res.put("res","fail");
        }
        return res;
    }

    @Override
    public Map<String, Object> getDeliveryCountOfDayByNameAndDateRange(String wangdian, String dateBgn, String dateEnd) {
        List<Orgdaily> orgdailyList = orgdailyMapper.getByNameAndDateRange(wangdian, dateBgn, dateEnd);
        Map<String,Object> res=new HashMap<>();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        if(!orgdailyList.isEmpty()) {
            List<String> dateList=new ArrayList<>();
            List<Integer>  deliveryCountOfDayList=new ArrayList<>();
            for (Orgdaily orgdaily : orgdailyList) {
                dateList.add(sf.format(orgdaily.getBusinessDate()));

                deliveryCountOfDayList.add(orgdaily.getDeliveryCountOfDay());
            }
            res.put("date",dateList);
            res.put("deliveryCountOfDay",deliveryCountOfDayList);
            res.put("res","success");

        }else{
            res.put("res","fail");
        }
        return res;
    }

    @Override
    public Map<String, Object> getDeliveryCountRateByNameAndDateRange(String wangdian, String dateBgn, String dateEnd) {
        List<Orgdaily> orgdailyList = orgdailyMapper.getByNameAndDateRange(wangdian, dateBgn, dateEnd);
        Map<String,Object> res=new HashMap<>();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        if(!orgdailyList.isEmpty()) {
            List<String> dateList=new ArrayList<>();
            List<Double>  deliveryCountRateList=new ArrayList<>();
            for (Orgdaily orgdaily : orgdailyList) {
                dateList.add(sf.format(orgdaily.getBusinessDate()));

                deliveryCountRateList.add((double)orgdaily.getDeliveryCountRate() / 100);
            }
            res.put("date",dateList);
            res.put("deliveryCountRate",deliveryCountRateList);
            res.put("res","success");

        }else{
            res.put("res","fail");
        }
        return res;
    }


    @Override
    public Map<String, Object> getShangquanfByNameAndYuefenRange(String wangdian, String yuefenBgn, String yuefenEnd) {
        List<Orgmonth> orgmonthList = orgmonthMapper.getByNameAndYuefenRange(wangdian, yuefenBgn, yuefenEnd);
        Map<String,Object> res=new HashMap<>();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM");
        if(!orgmonthList.isEmpty()) {
            List<String> yuefenList=new ArrayList<>();
            List<Double>  shangquanfList=new ArrayList<>();
            for (Orgmonth orgmonth : orgmonthList) {
                yuefenList.add(orgmonth.getYuefen());
                shangquanfList.add(orgmonth.getShangquanf());
            }
            res.put("yuefen",yuefenList);
            res.put("shangquanf",shangquanfList);
            res.put("res","success");
        }else{
            res.put("res","fail");
        }
        return res;
    }

    @Override
    public Weight getByYuefen(String yuefen) {
        return weightMapper.getByYuefen(yuefen);
    }

    @Override
    public double getAvgDeliveryOfMonth(String wangdian, String yuefen) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String endDate = yuefen + "-01";
        Date date;
        try {
            date = format.parse(endDate);
        } catch (ParseException e) {
            e.printStackTrace();
            return 0;
        }
        Calendar cal = Calendar.getInstance();  //获取当前日期
        cal.setTime(date);
        cal.add(Calendar.MONTH, -1);
        cal.set(Calendar.DAY_OF_MONTH, 1);  //设置为1号,当前日期既为本月第一天
        String startDate = format.format(cal.getTime());
        if (orgdailyMapper.getAvgDeliveryOfMonth(wangdian, startDate, endDate) == null) {
            // TODO: 没数据用到目前为止平均 / 设置默认值
            return 1;
        }
        return orgdailyMapper.getAvgDeliveryOfMonth(wangdian, startDate, endDate);
    }

    @Override
    public int getTotalDeliveryCountOfMonth(String wangdian, String yuefen) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String endDate = yuefen + "-01";
        Date date;
        try {
            date = format.parse(endDate);
        } catch (ParseException e) {
            e.printStackTrace();
            return 0;
        }
        Calendar cal=Calendar.getInstance();  //获取当前日期
        cal.setTime(date);
        cal.add(Calendar.MONTH, -1);
        cal.set(Calendar.DAY_OF_MONTH,1);  //设置为1号,当前日期既为本月第一天
        String startDate = format.format(cal.getTime());
        if (orgdailyMapper.getAvgDeliveryOfMonth(wangdian, startDate, endDate) == null) {
            return 1;
        }
        return orgdailyMapper.getTotalDeliveryCountOfMonth(wangdian, startDate, endDate);
    }

    @Override
    public Integer getOrgNum() {
        return orgmonthMapper.queryOrgNum();
    }

    @Override
    public Integer getOrgNumByProv(String provence) {
        return orgmonthMapper.queryOrgNumByProv(provence);
    }

    @Override
    public Integer getEvaluateNum() {
        return orgmonthMapper.queryEvaluateNum();
    }

    @Override
    public int[] getOrgNumOfType(String yuefen) {
        int[] nums = new int[5];
        nums[0] = orgmonthMapper.getCountByYuefen(yuefen, null);
        nums[1] = orgmonthMapper.getCountByYuefen(yuefen, "小规模");
        nums[2] = orgmonthMapper.getCountByYuefen(yuefen, "中规模");
        nums[3] = orgmonthMapper.getCountByYuefen(yuefen, "大规模");
        nums[4] = orgmonthMapper.getCountByYuefen(yuefen, "超大规模");
        return nums;
    }

    @Override
    public Double getLoadScoreByYuefenAndLoadRankAndType(int loadrank, String yuefen, String type) {
        return orgmonthMapper.getLoadScoreByYuefenAndLoadRankAndType(loadrank, yuefen, type);
    }

    @Override
    public Double getStaffScoreByYuefenAndStaffRankAndType(int staffrank, String yuefen, String type) {
        return orgmonthMapper.getStaffScoreByYuefenAndStaffRankAndType(staffrank, yuefen, type);
    }

    @Override
    public Double getAgeScoreByYuefenAndAgeRankAndType(int agerank, String yuefen, String type) {
        return orgmonthMapper.getAgeScoreByYuefenAndAgeRankAndType(agerank, yuefen, type);
    }

    @Override
    public Double getLaborScoreByYuefenAndLaborRankAndType(int laborrank, String yuefen, String type) {
        return orgmonthMapper.getLaborScoreByYuefenAndLaborRankAndType(laborrank, yuefen, type);
    }

    @Override
    public Double getDailyScoreByYuefenAndDailyRankAndType(int dailyrank, String yuefen, String type) {
        return orgmonthMapper.getDailyScoreByYuefenAndDailyRankAndType(dailyrank, yuefen, type);
    }

    @Override
    public Double getMaxScoreByYuefenAndMaxRankAndType(int maxrank, String yuefen, String type) {
        return orgmonthMapper.getMaxScoreByYuefenAndMaxRankAndType(maxrank, yuefen, type);
    }


}
